package org.ccay.core.orm.plugins;

import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.MappedStatement.Builder;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.ccay.core.orm.ExtendedSqlSource;
import org.ccay.core.util.StringUtil;

/**
 * myBatis的拦截类，用来处理&lt;![CDATA[ ]] &gt; 中的自定义标签
 * &lt;addProgramTag&gt;&lt;addFilter&gt;
 * @since 2011-12-14
 */
@Intercepts( {
		@Signature(type = Executor.class, method = "query", args = {
				MappedStatement.class, Object.class, RowBounds.class,
				ResultHandler.class }),
		@Signature(type = Executor.class, method = "update", args = {
				MappedStatement.class, Object.class }) })
public class CdataTagInterceptor implements Interceptor {

	/* (non-Javadoc)
	 * @see org.apache.ibatis.plugin.Interceptor#intercept(org.apache.ibatis.plugin.Invocation)
	 */
	public Object intercept(Invocation invocation) throws Throwable {

		Object[] args = invocation.getArgs();
		MappedStatement stmt = (MappedStatement) args[0];
		args[0] = buildMappedStatement(stmt);

		return invocation.proceed();
	}

	/* (non-Javadoc)
	 * @see org.apache.ibatis.plugin.Interceptor#plugin(java.lang.Object)
	 */
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	/* (non-Javadoc)
	 * @see org.apache.ibatis.plugin.Interceptor#setProperties(java.util.Properties)
	 */
	public void setProperties(Properties properties) {
	}

	/**
	 * 重建MappedStatement对象, 用delegate的方式, 接入ExtendedSqlSource对象
	 * @see org.ccay.core.orm.ExtendedSqlSource
	 * 
	 * @since 2011-12-14
	 * @param mappedStatement
	 * @return
	 */
	public MappedStatement buildMappedStatement(MappedStatement mappedStatement) {
		Builder builder = new Builder(mappedStatement.getConfiguration(),
				mappedStatement.getId(), new ExtendedSqlSource(mappedStatement
						.getConfiguration(), mappedStatement.getSqlSource()),
				mappedStatement.getSqlCommandType());

		builder.resource(mappedStatement.getResource());
		builder.parameterMap(mappedStatement.getParameterMap());
		builder.resultMaps(mappedStatement.getResultMaps());
		builder.fetchSize(mappedStatement.getFetchSize());
		builder.timeout(mappedStatement.getTimeout());
		builder.statementType(mappedStatement.getStatementType());
		builder.resultSetType(mappedStatement.getResultSetType());
		builder.cache(mappedStatement.getCache());
		builder.flushCacheRequired(mappedStatement.isFlushCacheRequired());
		builder.useCache(mappedStatement.isUseCache());
		builder.keyGenerator(mappedStatement.getKeyGenerator());
		builder.keyProperty(StringUtil.join(mappedStatement.getKeyProperties(), ","));

		return builder.build();
	}
}
